﻿using Ganjine.Common;
using Ganjine.DataModel;
using SQLitePCL;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409

namespace Ganjine
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        public static int _minSearchTextLength = 2;
        public static int _maxSearchResultsCount = 5000;
        public static SQLiteConnection conn = null;
        public static DataSource dataSource;
        public static List<PoemItem> favorites = new List<PoemItem>();
        public static List<FontItem> fonts = new List<FontItem>();
        public static string SearchQuery = "";
        public static FontFamily DefaultFont;
        public static double DefaultFontSize;
        public string sErrorLog = "";
        public static string CurPageArg = "";
        public static bool askForReview = false;
        public static int SearchSourceIndex = 0;
        public static Dictionary<string, double> scrollPosition = new Dictionary<string, double>();

        public static class SearchPageState
        {
            public static int firstNewPoet = 1;
            public static List<PoemItem> items = new List<PoemItem>();
            public static List<string> stringItems = new List<string>();
            public static double scrollPosition = 0.0;
            public static int PoetIndex = -1;

            public static void Reset()
            {
                scrollPosition = 0.0;
                items.Clear();
                stringItems.Clear();
                firstNewPoet = 1;
                PoetIndex = -1;
            }
        }

        /// <summary>
        /// Allows tracking page views, exceptions and other telemetry through the Microsoft Application Insights service.
        /// </summary>
        public static Microsoft.ApplicationInsights.TelemetryClient TelemetryClient;

        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            TelemetryClient = new Microsoft.ApplicationInsights.TelemetryClient();


            this.InitializeComponent();
            this.Suspending += OnSuspending;




            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;

            Object theme = localSettings.Values["currentTheme"];


            if (theme == null)
            {
                // No data
                localSettings.Values["currentTheme"] = 0;
                RequestedTheme = ApplicationTheme.Light;
            }
            else
            {
                if (((int)theme == 1) || ((int)theme == 3))
                {
                    RequestedTheme = ApplicationTheme.Dark;
                }
                else
                {
                    RequestedTheme = ApplicationTheme.Light;
                }
            }

            Object value = localSettings.Values["runCount"];


            if (value == null)
            {
                // No data
                localSettings.Values["runCount"] = 1;
            }
            else
            {
                // Access data in value
                if ((int.Parse(localSettings.Values["runCount"].ToString()) > 6) && (localSettings.Values["AskedForReview"] == null))
                {
                    askForReview = true;
                }
                localSettings.Values["runCount"] = int.Parse(localSettings.Values["runCount"].ToString()) + 1;
            }

        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override async void OnLaunched(LaunchActivatedEventArgs e)
        {

            dataSource = new DataSource();


            var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
            if (bounds.Width > 720)
            {
                DefaultFontSize = 30;
            }
            else
            {
                DefaultFontSize = 20;
            }

            await dataSource.InitializeSettings();

            /* IMPORTANT NOTE: Favorites should be loaded in MainPage, because
                1. They might be changed when MainPage is loaded again (back)
                2. In the first run, database is not copied yet in this stage. */

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif


            Frame rootFrame = Window.Current.Content as Frame;
            var view = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
            view.SetPreferredMinSize(new Size(900, 780));

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;
                rootFrame.Navigated += OnNavigated;


                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // Restore the saved session state only when appropriate
                    try
                    {

                        await SuspensionManager.RestoreAsync();
                        SearchQuery = SuspensionManager.SessionState["SearchQuery"].ToString();
                        SearchSourceIndex = int.Parse(SuspensionManager.SessionState["SearchSourceIndex"].ToString());
                    }
                    catch (SuspensionManagerException)
                    {
                        // Something went wrong restoring state.
                        // Assume there is no state and continue
                    }
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;


                // Register a handler for BackRequested events and set the
                // visibility of the Back button
                SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;

                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                    rootFrame.CanGoBack ?
                    AppViewBackButtonVisibility.Visible :
                    AppViewBackButtonVisibility.Collapsed;

            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }


            // Ensure the current window is active
            Window.Current.Activate();

            App.fonts.Add(new FontItem("نازنین", (FontFamily)App.Current.Resources["NazaninFontFamily"]));
            App.fonts.Add(new FontItem("نستعلیق", (FontFamily)App.Current.Resources["NastaliqFontFamily"]));
            App.fonts.Add(new FontItem("میترا", (FontFamily)App.Current.Resources["MitraFontFamily"]));
            App.fonts.Add(new FontItem("رویا", (FontFamily)App.Current.Resources["RoyaFontFamily"]));
            App.fonts.Add(new FontItem("یکان", (FontFamily)App.Current.Resources["YekanFontFamily"]));
            App.fonts.Add(new FontItem("کامران", (FontFamily)App.Current.Resources["KamranFontFamily"]));
            App.fonts.Add(new FontItem("آرش", (FontFamily)App.Current.Resources["ArashFontFamily"]));
            App.fonts.Add(new FontItem("آراز", (FontFamily)App.Current.Resources["ArazFontFamily"]));
            App.fonts.Add(new FontItem("دست‌نویس", (FontFamily)App.Current.Resources["DastNevisFontFamily"]));
            App.fonts.Add(new FontItem("دمرل", (FontFamily)App.Current.Resources["DomrolFontFamily"]));
            App.fonts.Add(new FontItem("ثلث", (FontFamily)App.Current.Resources["ThuluthFontFamily"]));
            App.fonts.Add(new FontItem("ویندوز", (FontFamily)App.Current.Resources["DefaultFontFamily"]));
        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

            SuspensionManager.SessionState["SearchQuery"] = SearchQuery;
            SuspensionManager.SessionState["SearchSourceIndex"] = SearchSourceIndex;
            await SuspensionManager.SaveAsync();
            deferral.Complete();
        }


        private void OnNavigated(object sender, NavigationEventArgs e)
        {
            // Each time a navigation event occurs, update the Back button's visibility
            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                ((Frame)sender).CanGoBack ?
                AppViewBackButtonVisibility.Visible :
                AppViewBackButtonVisibility.Collapsed;
        }


        private void OnBackRequested(object sender, BackRequestedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame.CanGoBack)
            {
                e.Handled = true;
                rootFrame.GoBack();
            }
        }

    }
}
